#include "cmd.h"

int is_internal_cmd(string *str)
{
	if(str_equals(str, "exit") || str_equals(str, "help") || str_equals(str, "cd") || str_equals(str, "pwd") ||
		str_equals(str, "fg") || str_equals(str, "bg") || str_equals(str, "jobs") || str_equals(str, "history"))
		return 1;
	else return 0;
}

int execute_internal_cmd(command *cmd)
{
	string *argv = (string *) ll_get_index(cmd->args, 0);

	if(str_equals(argv, "exit"))
	{
		return EXIT;
	}
	else if(str_equals(argv, "help"))
	{
		builtin_help();
		return SUCCESS;
	}
	else if(str_equals(argv, "jobs"))
	{
		builtin_jobs();
		return SUCCESS;
	}
	else if(str_equals(argv, "fg"))
	{
		builtin_fg_bg((string *) ll_get_index(cmd->args, 1), 1);
		return SUCCESS;
    }
	else if(str_equals(argv, "bg"))
	{
		builtin_fg_bg((string *) ll_get_index(cmd->args,1), 2);
		return SUCCESS;
	}
	else if(str_equals(argv, "cd"))
	{
		builtin_cd((string *) ll_get_index(cmd->args, 1));
		return SUCCESS;
	}
	else if(str_equals(argv, "pwd"))
    {
        builtin_pwd();
        return SUCCESS;
    }
	else if(str_equals(argv, "history"))
	{
	    builtin_history();
	    return SUCCESS;
	}

    return FAILURE;
}

void builtin_help()
{
	printf("help: show this\n");
	printf("jobs: show running, stopped or continued processes\n");
	printf("fg [pid]: bring the process identified by pid to foreground\n");
	printf("bg [pid]: continue the stopped process identified by pid in background\n");
	printf("cd [path]: change the current directory to path\n");
	printf("history: show the lasts commands\n");
	printf("exit: exit the mustash\n");
}

void builtin_jobs()
{
	process *p;
	ll_iterator *it = ll_get_iterator(process_list);

	while(!ll_is_end(it))
	{
		p = (process *) ll_get(it);

		if(p->status == RUNNING || p->status == CONTINUED) printf("[RUNNING] ");
		else /* if (p->status == STOPPED) */ printf("[STOPPED] ");

		if (p->ground == FG) printf("[FG] ");
		else printf("[BG] ");

		printf("%d\n", p->pid);

		ll_next(it);
	}
	free(it);
}

void builtin_fg_bg(string *arg, int mode)
{
	pid_t pid = -2;
	process *p;

	/* Se existe argumento então pega o PID */
	if(arg != NULL)
	{
		/* string pid para int */
		pid = atoi(str_to_array(arg));

		/* Se o argumento determinado for inválido */
		if(pid == 0)
		{
			printf("Illegal argument. Use: %s [pid]\n", mode==1 ? "fg" : "bg");
			return ;
		}
		else /* Não é inválido, manda o sinal para pid */
		{

			get_process(pid)->ground = mode == 1 ? FG : BG;
			kill(pid, SIGCONT);
			if(mode == 1) wait_child(pid); /* fg waits */
		}
	}

	else /* Manda pro primeiro da fila de processos */
	{

		p = (process *) ll_get_index(process_list, 0);

		if(p != NULL)
		{
			get_process(p->pid)->ground = mode==1 ? FG : BG;
			kill(p->pid, SIGCONT);
			if(mode == 1) wait_child(p->pid); /* fg waits */
		}
	}
}

void builtin_pwd()
{
    printf("%s\n", getenv("PWD"));
}

void builtin_cd(string *path)
{
	string *aux;
	char *arr;
	char *dir;

	if(path == NULL)
	{
	    if(chdir(getenv("HOME")) == -1) perror("Couldn't change the current directory\n");
	}
	else
	{
		if(str_starts_with(path, "/"))
			arr = str_to_array(path);
		else
		{
			aux = str_new();
			dir = getenv("PWD");

			str_cats(aux, dir);
			str_catc(aux, '/');
			str_cat(aux, path);

			arr = str_to_array(aux);

			str_delete(aux);
		}

		setenv("PWD", arr, 1);
		if(chdir(arr) == -1) perror("Couldn't change the current directory\n");
		free(arr);
	}
}

void builtin_history()
{
    char input[MAX_INPUT];
    int count = 1;

    history_open();

    while(fgets(input, MAX_INPUT, history) != NULL)
    {
        printf("%5d %s", count, input);
        count++;
    }

    history_close();
}
